package net.peelmeagrape.hibernate;

import net.peelmeagrape.hibernate.xmlgen.*;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Maps properties of a child object to columns of the table of a parent class.
 * Components may, in turn, declare their own properties, components or collections.
 * <br/>
 * <br/>
 * H8A8 will automatically process annotations on the child class. The child class is
 * the type of the field or property. The child class should contain
 * {@link Property}, {@link ManyToOne}, {@link OneToOne} and collection mapping
 * annotations which map properties of the child object to the parent table.
 * The child class also may contain a
 * {@link Parent} annotation that maps a property back to the containing entity.
 */
@Target({METHOD,FIELD}) @Retention(RUNTIME)
@XmlElement(name="component")
@AddPropertyNameAsAttribute(name="name")
public @interface Component
{
    @XmlAttribute("class")
            @DefaultFromPropertyType
            @ProcessTargetClass()
            Class[] targetClass() default {};

    /**
     * The strategy Hibernate should use for accessing the property value. This may be one of
     * 'property', 'field', 'embedded', or the name of a subclass of {@link org.hibernate.property.PropertyAccessor}.
     */
    @XmlAttribute String access() default "property";

    /**
     * Do the mapped columns appear in SQL UPDATEs?
     */
    @XmlAttribute boolean update() default true;

    /**
     *  Do the mapped columns appear in SQL INSERTs?
     */
    @XmlAttribute boolean insert() default true;

    /**
     * Specifies that updates to this component do or do not require acquisition of the optimistic lock.
     * In other words, determines if a version increment should occur when this property is dirty.
     */
    @XmlAttribute("optimistic-lock") boolean optimisticLock() default true;

    /**
     * Specifies that a unique constraint exists upon all mapped columns of the component.
     */
    @XmlAttribute boolean unique() default false;

    /**
     * Specifies that this component should be fetched lazily when the instance variable is
     * first accessed (requires build-time bytecode instrumentation).
     */
    @XmlAttribute boolean lazy() default false;
    @XmlAttribute String node() default "";
    @ChildElement(0) Meta[] meta() default {};

    @FindParentElement(name="natural-id") boolean naturalId() default false;
    @FindParentElement(
        name="join",
        idAttributeName = "table",
        reorderNewParent = "component|sql-insert?,sql-update?,sql-delete?"
    )
        String[] join() default {};

    /**
     * Specify that this property is part of a properties grouping. See {@link Properties}.
     */
    @FindParentElement(
        name="properties",
        idAttributeName = "name"
    )
        String[] properties() default {};
}
